package linestrategy

import (
	"codejy/analysis/lineanalysis"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/utils"
	"fmt"
	"strings"
)

func init() {
	globalfunc.RegisterFuncAll("LineStrategyMode", LineStrategyMode)
	globalfunc.RegisterFuncAll("SkipCommentAndEmpty", SkipCommentAndEmpty)
}

type LineStrategy interface {
	// 策略id
	getId() int
	// 执行策略
	Execute(threadStore *structdef.ThreadStore)
}

// key策略代号,value策略
var StrategieMap = make(map[int]LineStrategy)

// 注册策略
func RegisterStrategy(strategy LineStrategy) {
	//添加到策略列表
	StrategieMap[strategy.getId()] = strategy
}

// 策略模式
func LineStrategyMode(threadStore *structdef.ThreadStore) {
	// 策略模式,处理各种代码
	code := threadStore.Code
	strategy, p := StrategieMap[code.LineCodeType]
	if !p {
		panic(fmt.Sprintf("没有找到执行此代码的策略,请检查语法是否正确,问题的行代码: %s", code))
	}
	strategy.Execute(threadStore)
}

// 这种执行方式只适用于文件行代码块执行,比如if for ,不能作用在函数里
func LineExecute(threadStore *structdef.ThreadStore, startIndex, endIndex int) {
	// 策略模式,处理各种代码
	for i := startIndex; i < endIndex; i++ {
		//设置当前操作指针,指针指向当前操作行
		threadStore.CurrentPoint = i
		//获取当前文件所有行代码
		codes := threadStore.Codes
		//分析当前操作行代码
		handleFilePath := threadStore.HandleFilePath
		definition := structdef.AnalyseLineCodeDefinition(threadStore, codes[i], handleFilePath)
		codes[i] = definition
		//添加当前行代码
		threadStore.Code = codes[i]
		//添加错误日志
		store.AddErrorLog(threadStore, store.NewRecordLog(threadStore, codes[i])) //添加错误日志
		utils.LimitSpeed(threadStore)
		//判断是否是break,或者是否是break运行
		if codes[i].LineCodeType == lineanalysis.Break || threadStore.BreakFlag {
			threadStore.BreakFlag = true
			return
		}
		//判断是否是continue,或者是否是continue运行
		if codes[i].LineCodeType == lineanalysis.Continue || threadStore.ContinueFlag {
			threadStore.ContinueFlag = true
			return
		}

		utils.CodeExecutionTime("行代码执行耗时情况", threadStore, func() {
			LineStrategyMode(threadStore) //策略模式,处理各种行代码
		})

		//判断是否是to,或者是否是to运行 ,如果是to,那么就跳出到上级, 因为不是函数,所以不能设置false
		if codes[i].LineCodeType == lineanalysis.To || threadStore.ReturnFlag {
			return
		}
		//获取当前操作指针,调整指针位置
		i = threadStore.CurrentPoint

	}
}

// 去除注释和空格,验证赋值变量名称是否合法
func SkipCommentAndEmpty(currentLineCodes []structdef.LineCodeDefinition) []structdef.LineCodeDefinition {

	for i := 0; i < len(currentLineCodes); i++ {
		//清除前后空格
		currentLineCodes[i].LineContent = strings.TrimSpace(currentLineCodes[i].LineContent)
		//判断是否是空行
		if currentLineCodes[i].LineContent == "" {
			//删除数据
			currentLineCodes = append(currentLineCodes[:i], currentLineCodes[i+1:]...)
			i--
			continue
		}

		//判断是否是多行字符串"""
		if strings.HasSuffix(currentLineCodes[i].LineContent, "\"\"\"") {
			//删除多余的空格
			currentLineCodes[i].LineContent = strings.ReplaceAll(currentLineCodes[i].LineContent, " ", "")
			//跳过多行字符串
			for {
				i++
				if currentLineCodes[i].LineContent == "\"\"\"" {
					break
				}
			}
			continue
		}

		var mapPlaceholder map[string]string
		//将字符串转换为占位符
		if strings.Contains(currentLineCodes[i].LineContent, "\"") {
			replace, str := utils.StrReplace(currentLineCodes[i].LineContent)
			currentLineCodes[i].LineContent = str
			mapPlaceholder = replace
		}
		//删除全部空格
		currentLineCodes[i].LineContent = strings.ReplaceAll(currentLineCodes[i].LineContent, " ", "")
		//如果是赋值语句,那么就验证赋值语句的变量名称是否合法
		if strings.Contains(currentLineCodes[i].LineContent, "=") {
			isAssignmentStatement := globalfunc.ExecuteFunc("IsVariableDefine", currentLineCodes[i].LineContent).(bool)
			if isAssignmentStatement { //如果是赋值语句,那么就验证赋值语句的变量名称是否合法
				var variableName string
				//判断是否有等号
				index := strings.Index(currentLineCodes[i].LineContent, "=")
				if index == -1 {
					//没有等号去除var
					variableName = currentLineCodes[i].LineContent[3:]
				}
				//有等号去除var和等号
				variableName = currentLineCodes[i].LineContent[3:index]
				globalfunc.ExecuteFunc("IsVariableNameLegal", variableName)
			}
		}

		//判断开头否是注释
		if strings.HasPrefix(currentLineCodes[i].LineContent, "//") {
			//删除数据
			currentLineCodes = append(currentLineCodes[:i], currentLineCodes[i+1:]...)
			i--
			//将字符串替换回来
			if mapPlaceholder != nil {
				currentLineCodes[i].LineContent = utils.StrRestore(currentLineCodes[i].LineContent, mapPlaceholder)
			}
			continue
		}
		//判断在行尾部的注释
		if strings.Contains(currentLineCodes[i].LineContent, "//") {
			//获取当前行最后一个//的下标
			index := strings.Index(currentLineCodes[i].LineContent, "//")
			//如果是-1,那么就是没有找到,那么就是没有注释
			if index == -1 {
				//将字符串替换回来
				if mapPlaceholder != nil {
					currentLineCodes[i].LineContent = utils.StrRestore(currentLineCodes[i].LineContent, mapPlaceholder)
				}
				continue
			}
			//删除数据
			currentLineCodes[i].LineContent = currentLineCodes[i].LineContent[:index]
			//将字符串替换回来
			if mapPlaceholder != nil {
				currentLineCodes[i].LineContent = utils.StrRestore(currentLineCodes[i].LineContent, mapPlaceholder)
			}
			continue
		}
		//判断是否是多行注释
		if strings.HasPrefix(currentLineCodes[i].LineContent, "/*") {
			//如果是多行注释,那么就一直循环,直到找到多行注释结束
			for j := i; j < len(currentLineCodes); {
				//如果是多行注释结束,那么就跳出循环
				if strings.HasSuffix(currentLineCodes[i].LineContent, "*/") {
					//删除数据
					currentLineCodes = append(currentLineCodes[:j], currentLineCodes[j+1:]...)
					i = j - 1
					break
				}
				//删除数据
				currentLineCodes = append(currentLineCodes[:j], currentLineCodes[j+1:]...)
			}
		}
		//将字符串替换回来
		if mapPlaceholder != nil {
			currentLineCodes[i].LineContent = utils.StrRestore(currentLineCodes[i].LineContent, mapPlaceholder)
		}

	}
	return currentLineCodes
}
